package com.dana.gomoku.match;

import com.dana.gomoku.model.User;
import com.dana.gomoku.room.Room;
import com.dana.gomoku.room.RoomManager;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

//这是一个匹配器,根据玩家天梯分数来匹配实力相近的对手
@Component
@Slf4j
public class Matcher {
    /**
     * 多个线程操作一个队列会存在线程安全问题,我们需要保证线程安全
     */
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private RoomManager roomManager;
    private ObjectMapper objectMapper=new ObjectMapper();
    private Queue<User> nomalQueue=new LinkedList<>();
    private Queue<User> highQueue=new LinkedList<>();
    private Queue<User> veryHighQueue=new LinkedList<>();

    //根据玩家天梯分加入相应的队列
    public void add(User user){
        if (user.getScore()<2000){
           synchronized (nomalQueue){
               nomalQueue.offer(user);
               nomalQueue.notify();
               log.info("玩家"+user.getUsername()+"加入队列");
           }
        }else if (user.getScore()>=2000&&user.getScore()<3000){
            synchronized (highQueue){
                highQueue.offer(user);
                highQueue.notify();
                log.info("玩家"+user.getUsername()+"加入队列");
            }
        }else {
           synchronized (veryHighQueue){
               veryHighQueue.offer(user);
               veryHighQueue.notify();
               log.info("玩家"+user.getUsername()+"加入队列");
           }
        }
    }

    public void remove(User user){
        if (user.getScore()<2000){
           synchronized (nomalQueue){
               nomalQueue.remove(user);
               log.info("玩家"+user.getUsername()+"离开队列");
           }
        }else if (user.getScore()>=2000&&user.getScore()<3000){
            synchronized (highQueue){
                highQueue.remove(user);
                log.info("玩家"+user.getUsername()+"离开队列");
            }
        }else {
           synchronized (veryHighQueue){
               veryHighQueue.remove(user);
               log.info("玩家"+user.getUsername()+"离开队列");
           }
        }
    }

    //用三个线程扫描三个队列
    public Matcher(){
        Thread t1=new Thread(()->{
           while (true){
               handlerQueue(nomalQueue);
           }
        });
        t1.start();
        Thread t2=new Thread(()->{
           while (true){
               handlerQueue(highQueue);
           }
        });
        t2.start();
        Thread t3=new Thread(()->{
            while (true){
                handlerQueue(veryHighQueue);
            }
        });
        t3.start();
    }

    private void handlerQueue(Queue<User> matchQueue){
      synchronized (matchQueue){
          try {
              while (matchQueue.size()<2){
                  matchQueue.wait();
              }
              //1.匹配成功后在匹配队列移除,因为两人已经成功匹配进入房间不在匹配队列内了
              User player1 = matchQueue.poll();
              User player2 = matchQueue.poll();
              log.info("玩家1 player1 {} 玩家2 player2 {}" ,player1,player2);
              //2.获取当前玩家的webSocket会话,告知对方排到了谁
              WebSocketSession session1 = onlineUserManager.getFromGameHall(player1.getUserId());
              WebSocketSession session2 = onlineUserManager.getFromGameHall(player2.getUserId());
              if (session1==null){
                  matchQueue.offer(player2);
                  return;
              }
              if (session2==null){
                  matchQueue.offer(player1);
                  return;
              }
              if (session1==session2){
                  matchQueue.offer(player1);
                  return;
              }
              Room room=new Room();
              roomManager.add(room, player1.getUserId(), player2.getUserId());
              log.info("玩家 {} 进入房间",player1.getUsername());
              log.info("玩家 {} 进入房间",player2.getUsername());
              //5.告知客户端匹配成功
              MatchResponse resp1=new MatchResponse();
              resp1.setMessage("matchSuccess");
              resp1.setOk(true);
              session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp1)));
              MatchResponse resp2=new MatchResponse();
              resp2.setMessage("matchSuccess");
              resp2.setOk(true);
              session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp2)));
          } catch (IOException |InterruptedException e) {
              throw new RuntimeException(e);
          }
      }
    }
}
